﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using PluginInterface;
using SdmxMl.Common;
using SdmxMl.Multiplexor;
using SdmxMl.Manager;
using SdmxMl.Structure;
using Telerik.WinControls;
using Telerik.WinControls.UI;
using Telerik.WinControls.UI.Export;

namespace PluginMeb
{
    /// <summary>
    /// Plug-in control for MEB matrix managment
    /// </summary>
    public partial class UcMatrix : UserControl, IPlugin
    {
        #region Constantes

        private const string TXT_DO_EDIT = "Edit Matrix";
        private const string TXT_CAUTION = "Caution";
        private const string TXT_ERROR = "Plug-in Error";

        #endregion

        #region Internal members

        /// <summary>Worker for initial load of metadata </summary>
        private BackgroundWorker bw;
        /// <summary>Canton enum with CH added </summary>
        private CodeListType cltCanton;

        /// <summary>Cache for metadata used </summary>
        private MatrixCache matriceCache;

        private GridCreator matrixMgr;

        #endregion

        #region Constructor

        /// <summary>C'tor </summary>
        public UcMatrix()
        {
            InitializeComponent();
            SetMenuInitialState();
            StartBackgroundInitailMetaLoad();
        }
        #endregion

        #region Background initial loading

        private void StartBackgroundInitailMetaLoad()
        {
            // load in thread
            bw = new BackgroundWorker();
            bw.WorkerReportsProgress = false;
            bw.WorkerSupportsCancellation = false;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

            bw.RunWorkerAsync();
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Result is Exception)
            {
                RadMessageBox.Show(this, ((Exception)e.Result).Message, TXT_ERROR, 
                    MessageBoxButtons.OK, RadMessageIcon.Error);
            }
            else
                matriceCache = e.Result as MatrixCache;
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                e.Result = new MatrixCache();
            }
            catch (Exception ex)
            {
                e.Result = ex;
            }
        }

        private void WaitCacheLoaded()
        {
            // wait metacache fully constructed
            using (new SdmxMl.Helper.CWaitCursor())
            {
                while (matriceCache == null)
                {
                    radMenu1.Enabled = false;
                    Application.DoEvents();
                }
                radMenu1.Enabled = true;
            }
        }

        #endregion

        #region Menu States

        private void SetMenuInitialState()
        {
            SetMenuReadState();
            radMenuButtonEdit.Enabled = false;
            radMenuItemSchulDetail.Enabled = false;
        }

        private void SetMenuReadState()
        {
            radMenuButtonEdit.Text = TXT_DO_EDIT;
            radMenuButtonEdit.Enabled = true;
            radMenuItemNewSchulart.Enabled = false;
            radMenuItemDelRow.Enabled = false;
            radMenuItemAddRow.Enabled = false;
            radMenuItemDupliRow.Enabled = false;
            radMenuItemSchulDetail.Enabled = true;
            ledBulb.On = false;
        }

        private void SetMenuInEditionState()
        {
            radMenuButtonEdit.Text = "Save/Cancel";
            radMenuItemNewSchulart.Enabled = true;
            radMenuItemDelRow.Enabled = true;
            radMenuItemAddRow.Enabled = true;
            radMenuItemDupliRow.Enabled = true;
        }

        #endregion

        #region Plug-in User Control Load Event

        /// <summary> On load set initial state for controls and fill canton list selector </summary>
        /// <param name="sender"></param><param name="e"></param>
        private void UcMatrix_Load(object sender, EventArgs e)
        {
            try
            {
                using (new SdmxMl.Helper.CWaitCursor())
                {
                    ReferenceManager.TreeMgr.AppliClosing += new EventHandler(TreeMgr_AppliClosing);
                    ReferenceManager.TreeMgr.LanguageChange += new EventHandler(TreeMgr_LanguageChange);

                    CreateCantonWithConfederation();
                }
            }
            catch (Exception ex)
            {
                RadMessageBox.Show("Error occured during MEB plug-in initialisation! " + ex.Message,
                        TXT_ERROR, MessageBoxButtons.OK, RadMessageIcon.Error);
            }
        }

        /// <summary> Fetch Canton list and add confederation code at start. </summary>
        private void CreateCantonWithConfederation()
        {
            SmManager sm = new SmManager();
            cltCanton = sm.GetArtefact(SdmxArtefactType.CodeLists, new ArtefactRefBase(Mux.FullIdSmsAdapter(MatrixCache.FULLID_CANTON)), true) as CodeListType;

            // Create additional code for swiss 'CH')
            CodeType codeSwiss = new CodeType();
            codeSwiss.Id = "0";
            codeSwiss.Name.UpdateForLanguage("en", "Switzerland");
            codeSwiss.Name.UpdateForLanguage("de", "Schweiz");
            codeSwiss.Name.UpdateForLanguage("fr", "Suisse");
            codeSwiss.Name.UpdateForLanguage("it", "Svizzera");
            Annotation a = new Annotation("ABBREV");
            a.Text.UpdateDefaultText("CH");
            codeSwiss.AnnotationList.Add(a);

            cltCanton.CodeList.Insert(0, codeSwiss);
            foreach (CodeType c in cltCanton.CodeList)
                radMenuComboItemCanton.Items.Add(
                    new RadListDataItem(c.AnnotationList[0].Text.ToString() + " - " + c.Name.ToString(), c));
        }

        #endregion

        #region Language change Event

        /// <summary>On language change, reload grids with correct texts</summary>
        /// <param name="sender"></param><param name="e"></param>
        void TreeMgr_LanguageChange(object sender, EventArgs e)
        {
            try
            {
                // React only if cache fully loaded
                if (matrixMgr != null)
                    matrixMgr.UpdateLanguage();
            }
            catch (Exception ex)
            {
                RadMessageBox.Show(this, ex.Message, TXT_ERROR, MessageBoxButtons.OK, RadMessageIcon.Error);
            }
        }
        #endregion

        #region Application closing Event

        void TreeMgr_AppliClosing(object sender, EventArgs e)
        {
            try
            {
                if (matriceCache != null)
                    SavePreviousChanges(false); // no need to reload
            }
            catch (Exception ex)
            {
                RadMessageBox.SetThemeName(this.radGridView.ThemeName);
                RadMessageBox.Show(this, ex.Message, TXT_ERROR, MessageBoxButtons.OK, RadMessageIcon.Error);
            }
        }
        #endregion

        #region IPlugin Members

        /// <summary>Event is part of interface but not used </summary>
        public event PluginEvent PluginEventExposed
        {
            add { }
            remove { }
        }


        public void Init(System.Xml.XmlDocument xDoc, object obExtend)
        {
        }

        public UserControl VisualComponent()
        {
            return this;
        }

        public bool RequiresInit
        {
            get { return false; }
        }

        #endregion

        #region Matrix selection Event

        /// <summary> New matrix required</summary>
        /// <param name="sender"></param> <param name="e"></param>
        private void radMenuComboItemCanton_ComboBoxElement_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
        {
            // Avoid mouse quick selection in canton dropdown
            this.radGridView.Focus();

            // wait metacache fully constructed
            WaitCacheLoaded();

            // Do we need to save current grid ?
            SavePreviousChanges(true);

            // Load matrix grid according to selected canton item
            LoadMatrixInGrid(e.Position);
        }
        #endregion

        #region Matrix Loading

        private void LoadMatrixInGrid(int selectedCantonIndex)
        {
            using (new SdmxMl.Helper.CWaitCursor())
            {
                try
                {
                    // Create grid view if not yet done
                    if (matrixMgr == null)
                    {
                        matrixMgr = new GridCreator(this.radGridView, this.radGridViewKombi, matriceCache);
                        matrixMgr.CreateView();
                        matrixMgr.DataModified += new EventHandler(matrixMgr_DataModified);
                    }

                    // Load matching metadataset
                    matrixMgr.LoadUnboundData(selectedCantonIndex);
                }
                catch (Exception ex)
                {
                    RadMessageBox.Show(this, ex.Message, TXT_ERROR, MessageBoxButtons.OK, RadMessageIcon.Error);
                }
            }
        }

        void matrixMgr_DataModified(object sender, EventArgs e)
        {
            ledBulb.On = true;
        }

        #endregion

        #region Suppress Conditional formatting menu item

        /// <summary>
        /// Do not provide menu item for conditional formatting
        /// </summary>
        /// <param name="sender"></param> <param name="e"></param>
        private void radGridView_ContextMenuOpening(object sender, ContextMenuOpeningEventArgs e)
        {
            RadMenuItemBase item = this.GetRadMenuItemByText(e.ContextMenu, "Conditional Formatting");
            if (item != null)
            {
                e.ContextMenu.Items.Remove(item);
            }
        }

        private RadMenuItemBase GetRadMenuItemByText(RadDropDownMenu menu, string title)
        {
            foreach (RadMenuItemBase item in menu.Items)
            {
                if (item.Text == title)
                {
                    return item;
                }
            }

            return null;
        }
        #endregion

        #region Excel export

        /// <summary>Excel Export Event</summary>
        /// <param name="sender"></param> <param name="e"></param>
        private void radMenuItemExportExcel_Click(object sender, EventArgs e)
        {
            RunExportToExcelML();
        }

        /// <summary> Export Grid to Excel </summary>
        private void RunExportToExcelML()
        {
            try
            {
                ExportToExcelML excelExporter = new ExportToExcelML(this.radGridView);

                excelExporter.SummariesExportOption = SummariesOption.ExportAll;
                //set export settings
                excelExporter.ExportVisualSettings = false;
                excelExporter.ExportHierarchy = true;
                excelExporter.HiddenColumnOption = HiddenOption.DoNotExport;

                this.Cursor = Cursors.WaitCursor;
                saveFileDialog.Filter = "Excel (*.xls)|*.xls";
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    excelExporter.RunExport(saveFileDialog.FileName);

                    DialogResult dr = RadMessageBox.Show("The data in the grid was exported successfully. Do you want to open the file?",
                        "Export to Excel", MessageBoxButtons.YesNo, RadMessageIcon.Question);
                    if (dr == DialogResult.Yes)
                    {
                        System.Diagnostics.Process.Start(saveFileDialog.FileName);
                    }
                }
            }
            catch (Exception ex)
            {
                RadMessageBox.SetThemeName(this.radGridView.ThemeName);
                RadMessageBox.Show(this, ex.Message, "I/O Error", MessageBoxButtons.OK, RadMessageIcon.Error);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }
        #endregion

        #region Save edited matrix

        /// <summary> Save if needed and de-reserve matrix </summary>
        private bool SavePreviousChanges(bool reload)
        {
            bool saved = true;
            using (new SdmxMl.Helper.CWaitCursor())
            {
                try
                {
                    if (matrixMgr != null)
                    {
                        matrixMgr.TerminateCellEdition();
                        if (ledBulb.On)
                        {
                            if (MessageBox.Show("Save edited metadata ? ", "Matrix", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
                            {
                                matrixMgr.Save();
                            }
                            else
                            {
                                matrixMgr.CancelEdition(reload);
                                saved = false;
                            }
                        }
                        else
                        {   // No more reservation
                            matrixMgr.CancelEdition(reload);
                        }
                    }
                }
                catch (Exception ex)
                {
                    RadMessageBox.Show(this, ex.Message, TXT_ERROR, MessageBoxButtons.OK, RadMessageIcon.Error);
                }
                finally
                {
                    SetMenuReadState();
                }
            }
            return saved;
        }

        
        #endregion

        #region Request edition Event

        private void radMenuButtonEdit_Click(object sender, EventArgs e)
        {
            try
            {
                if (! matrixMgr.InEdition)
                {
                    matrixMgr.StartEdition();
                    SetMenuInEditionState();
                }
                else
                {
                    if (!SavePreviousChanges(true))
                        matrixMgr.LoadUnboundData(radMenuComboItemCanton.ComboBoxElement.SelectedIndex);
                 
                }
            }
            catch (Exception ex)
            {
                RadMessageBox.Show(this, ex.Message, TXT_ERROR, MessageBoxButtons.OK, RadMessageIcon.Error);
            }

        }
        #endregion

        #region Menu events

        private void RadMenuEventTreatment(object sender, EventArgs e)
        {
            try
            {
                // Schulart Edition
                if (sender == radMenuItemSchulDetail)
                {
                    matrixMgr.SchulartEdit(false);
                }

                // Schulart creation
                else if (sender == radMenuItemNewSchulart)
                {
                    matrixMgr.SchulartEdit(true);
                }
                // Adding row
                else if (sender == radMenuItemAddRow)
                {
                    matrixMgr.AddRow();
                }

                // Selected row duplication
                else if (sender == radMenuItemDupliRow)
                {
                    if (!matrixMgr.RowDuplicate())
                        RadMessageBox.Show(this, "No row is selected.", TXT_CAUTION, MessageBoxButtons.OK, RadMessageIcon.Error);
                }

                else if (sender == radMenuItemDelRow)
                {
                    if (radGridView.CurrentRow is GridViewDataRowInfo)
                    {
                        if (RadMessageBox.Show(this, "delete selected row ?", "Confirm", MessageBoxButtons.YesNo, RadMessageIcon.Question) == DialogResult.Yes)
                            matrixMgr.EraseCurrentRow();
                    }
                    else
                        RadMessageBox.Show(this, "No row is selected.", TXT_CAUTION, MessageBoxButtons.OK, RadMessageIcon.Error);
                }

                // Filtering option
                else if (sender == radMenuItemFiltering)
                {
                    RadMenuItem menuItem = sender as RadMenuItem;
                        radGridView.EnableFiltering = menuItem.IsChecked;
                }

                // Matrix import from Excel
                else if (sender == radMenuItemImportMatrix)
                {
                    ImportMetasetFromExcel import = new ImportMetasetFromExcel();
                    //import.RedefineParent();
                    import.ImportFromExcel(cltCanton, matriceCache.AgencyId);
                    //ImportNogaCorr imp = new ImportNogaCorr();
                    //imp.ImportFromExcel();
                }

                else if (sender == radMenuItemImportHclKombi)
                {
                    ImportHclKombi import = new ImportHclKombi(@"C:\Doc\MEB\hcl_kombi.xls");

                }
            }
            catch (Exception ex)
            {
                RadMessageBox.Show(this, ex.Message, TXT_ERROR, MessageBoxButtons.OK, RadMessageIcon.Error);
            }
        }
        #endregion

    }
}
